package roaring

func difference( []uint16,  []uint16,  []uint16) int {
	if len() == 0 {
		 = [:len()]
		copy(, )
		return len()
	}
	if len() == 0 {
		return 0
	}
	 := 0
	 := 0
	 := 0
	 = [:cap()]
	 := []
	 := []
	for {
		if  <  {
			[] = 
			++
			++
			if  >= len() {
				break
			}
			 = []
		} else if  ==  {
			++
			++
			if  >= len() {
				break
			}
			 = []
			if  >= len() {
				for ;  < len(); ++ {
					[] = []
					++
				}
				break
			}
			 = []
		} else { // if (val1>val2)
			++
			if  >= len() {
				for ;  < len(); ++ {
					[] = []
					++
				}
				break
			}
			 = []
		}
	}
	return 
}

func exclusiveUnion2by2( []uint16,  []uint16,  []uint16) int {
	if 0 == len() {
		 = [:len()]
		copy(, [:])
		return len()
	}
	if 0 == len() {
		 = [:len()]
		copy(, [:])
		return len()
	}
	 := 0
	 := 0
	 := 0
	 := []
	 := []
	 = [:cap()]
	for {
		if  <  {
			[] = 
			++
			++
			if  >= len() {
				for ;  < len(); ++ {
					[] = []
					++
				}
				break
			}
			 = []
		} else if  ==  {
			++
			++
			if  >= len() {
				for ;  < len(); ++ {
					[] = []
					++
				}
				break
			}
			if  >= len() {
				for ;  < len(); ++ {
					[] = []
					++
				}
				break
			}
			 = []
			 = []
		} else { // if (val1>val2)
			[] = 
			++
			++
			if  >= len() {
				for ;  < len(); ++ {
					[] = []
					++
				}
				break
			}
			 = []
		}
	}
	return 
}

// union2by2Cardinality computes the cardinality of the union
func union2by2Cardinality( []uint16,  []uint16) int {
	 := 0
	 := 0
	 := 0
	if 0 == len() {
		return len()
	}
	if 0 == len() {
		return len()
	}
	 := []
	 := []
	for {
		if  <  {
			++
			++
			if  >= len() {
				 += len() - 
				break
			}
			 = []
		} else if  ==  {
			++
			++
			++
			if  >= len() {
				 += len() - 
				break
			}
			if  >= len() {
				 += len() - 
				break
			}
			 = []
			 = []
		} else { // if (set1[k1]>set2[k2])
			++
			++
			if  >= len() {
				 += len() - 
				break
			}
			 = []
		}
	}
	return 
}

func intersection2by2(
	 []uint16,
	 []uint16,
	 []uint16,
) int {
	if len()*64 < len() {
		return onesidedgallopingintersect2by2(, , )
	} else if len()*64 < len() {
		return onesidedgallopingintersect2by2(, , )
	} else {
		return localintersect2by2(, , )
	}
}

// intersection2by2Cardinality computes the cardinality of the intersection
func intersection2by2Cardinality(
	 []uint16,
	 []uint16,
) int {
	if len()*64 < len() {
		return onesidedgallopingintersect2by2Cardinality(, )
	} else if len()*64 < len() {
		return onesidedgallopingintersect2by2Cardinality(, )
	} else {
		return localintersect2by2Cardinality(, )
	}
}

// intersects2by2 computes whether the two sets intersect
func intersects2by2(
	 []uint16,
	 []uint16,
) bool {
	if (len() == 0) || (len() == 0) {
		return false
	}
	if len()*64 < len() {
		return onesidedgallopingintersect2by2Bool(, )
	} else if len()*64 < len() {
		return onesidedgallopingintersect2by2Bool(, )
	} else {
		return intersects2by2Bool(, )
	}
}

func intersects2by2Bool(
	 []uint16,
	 []uint16,
) bool {
	 := 0
	 := 0
	 := []
	 := []
:
	for {

		if  <  {
			for {
				++
				if  == len() {
					break 
				}
				 = []
				if  >=  {
					break
				}
			}
		}
		if  <  {
			for {
				++
				if  == len() {
					break 
				}
				 = []
				if  >=  {
					break
				}
			}
		} else {
			// (set2[k2] == set1[k1])
			return true
		}
	}
	return false
}

func onesidedgallopingintersect2by2Bool(
	 []uint16,
	 []uint16,
) bool {
	 := 0
	 := 0
	 := []
	 := []
:
	for {
		if  <  {
			 = advanceUntil(, , len(), )
			if  == len() {
				break 
			}
			 = []
		}
		if  <  {
			++
			if  == len() {
				break 
			}
			 = []
		} else {
			// (set2[k2] == set1[k1])
			return true
		}

	}
	return false
}

func localintersect2by2(
	 []uint16,
	 []uint16,
	 []uint16,
) int {
	if (len() == 0) || (len() == 0) {
		return 0
	}
	 := 0
	 := 0
	 := 0
	 = [:cap()]
	 := []
	 := []
:
	for {
		if  <  {
			for {
				++
				if  == len() {
					break 
				}
				 = []
				if  >=  {
					break
				}
			}
		}
		if  <  {
			for {
				++
				if  == len() {
					break 
				}
				 = []
				if  >=  {
					break
				}
			}
		} else {
			// (set2[k2] == set1[k1])
			[] = 
			++
			++
			if  == len() {
				break
			}
			 = []
			++
			if  == len() {
				break
			}
			 = []
		}
	}
	return 
}

// / localintersect2by2Cardinality computes the cardinality of the intersection
func localintersect2by2Cardinality(
	 []uint16,
	 []uint16,
) int {
	if (len() == 0) || (len() == 0) {
		return 0
	}
	 := 0
	 := 0
	 := 0
	 := []
	 := []
:
	for {
		if  <  {
			for {
				++
				if  == len() {
					break 
				}
				 = []
				if  >=  {
					break
				}
			}
		}
		if  <  {
			for {
				++
				if  == len() {
					break 
				}
				 = []
				if  >=  {
					break
				}
			}
		} else {
			// (set2[k2] == set1[k1])
			++
			++
			if  == len() {
				break
			}
			 = []
			++
			if  == len() {
				break
			}
			 = []
		}
	}
	return 
}

func advanceUntil(
	 []uint16,
	 int,
	 int,
	 uint16,
) int {
	 :=  + 1

	if  >=  || [] >=  {
		return 
	}

	 := 1

	for + <  && [+] <  {
		 *= 2
	}
	var  int
	if + <  {
		 =  + 
	} else {
		 =  - 1
	}

	if [] ==  {
		return 
	}

	if [] <  {
		// means
		// array
		// has no
		// item
		// >= min
		// pos = array.length;
		return 
	}

	// we know that the next-smallest span was too small
	 += ( >> 1)

	 := 0
	for +1 !=  {
		 = ( + ) >> 1
		if [] ==  {
			return 
		} else if [] <  {
			 = 
		} else {
			 = 
		}
	}
	return 
}

func onesidedgallopingintersect2by2(
	 []uint16,
	 []uint16,
	 []uint16,
) int {
	if 0 == len() {
		return 0
	}
	 = [:cap()]
	 := 0
	 := 0
	 := 0
	 := []
	 := []
:

	for {
		if  <  {
			 = advanceUntil(, , len(), )
			if  == len() {
				break 
			}
			 = []
		}
		if  <  {
			++
			if  == len() {
				break 
			}
			 = []
		} else {

			[] = 
			++
			++
			if  == len() {
				break
			}
			 = []
			 = advanceUntil(, , len(), )
			if  == len() {
				break 
			}
			 = []
		}

	}
	return 
}

func onesidedgallopingintersect2by2Cardinality(
	 []uint16,
	 []uint16,
) int {
	if 0 == len() {
		return 0
	}
	 := 0
	 := 0
	 := 0
	 := []
	 := []
:

	for {
		if  <  {
			 = advanceUntil(, , len(), )
			if  == len() {
				break 
			}
			 = []
		}
		if  <  {
			++
			if  == len() {
				break 
			}
			 = []
		} else {

			++
			++
			if  == len() {
				break
			}
			 = []
			 = advanceUntil(, , len(), )
			if  == len() {
				break 
			}
			 = []
		}

	}
	return 
}

func binarySearch( []uint16,  uint16) int {
	 := 0
	 := len() - 1
	for +16 <=  {
		 := int(uint32(+) >> 1)
		 := []
		if  <  {
			 =  + 1
		} else if  >  {
			 =  - 1
		} else {
			return 
		}
	}
	for ;  <= ; ++ {
		 := []
		if  >=  {
			if  ==  {
				return 
			}
			break
		}
	}
	return -( + 1)
}

// searchResult provides information about a search request.
// The values will depend on the context of the search
type searchResult struct {
	value      uint16
	index      int
	exactMatch bool
}

// notFound returns a bool depending the search context
// For cases `previousValue` and `nextValue` if target is present in the slice
// this function will return `true` otherwise `false`
// For `nextAbsentValue` and `previousAbsentValue` this will only return `False`
func ( *searchResult) () bool {
	return !.exactMatch
}

// outOfBounds indicates whether the target was outside the lower and upper bounds of the container
func ( *searchResult) () bool {
	return .index <= -1
}

// binarySearchUntil is a helper function around binarySearchUntilWithBounds
// The user does not have to pass in the lower and upper bound
// The lower bound is taken to be `0` and the upper bound `len(array)-1`
func binarySearchUntil( []uint16,  uint16) searchResult {
	return binarySearchUntilWithBounds(, , 0, len()-1)
}

// binarySearchUntilWithBounds returns a `searchResult`.
// If an exact match is found the `searchResult{target, <index>, true}` will be returned, where `<index>` is
// `target`s index in `array`, and `result.notFound()` evaluates to `false`.
// If a match is not found, but `target` was in-bounds then the result.index will be the closest smaller value
// Example: [ 8,9,11,12] if the target was 10, then `searchResult{9, 1, false}` will be returned.
// If `target` was out of bounds `searchResult{0, -1, false}` will be returned.
func binarySearchUntilWithBounds( []uint16,  uint16,  int,  int) searchResult {
	 := 

	 := -1

	if  < [] {
		return searchResult{0, , false}
	}

	if  > [] {
		return searchResult{0, len(), false}
	}

	for  <=  {
		 := ( + ) / 2
		 := []

		if  ==  {
			return searchResult{, , true}
		}

		if  <  {

			if  > 0 &&  > [-1] {
				return searchResult{[-1],  - 1, false}
			}

			 = 
		} else {
			if  <  &&  < [+1] {
				return searchResult{, , false}
			}
			 =  + 1
		}

	}

	return searchResult{[], , false}
}

// binarySearchPast is a wrapper around binarySearchPastWithBounds
// The user does not have to pass in the lower and upper bound
// The lower bound is taken to be `0` and the upper bound `len(array)-1`
func binarySearchPast( []uint16,  uint16) searchResult {
	return binarySearchPastWithBounds(, , 0, len()-1)
}

// binarySearchPastWithBounds looks for the smallest value larger than or equal to `target`
// If `target` is out of bounds a `searchResult` indicating out of bounds is returned
// `target` does not have to exist in the slice.
//
// Example:
// Suppose the slice is [...10,13...] with `target` equal to 11
// The searchResult will have searchResult.value = 13
func binarySearchPastWithBounds( []uint16,  uint16,  int,  int) searchResult {
	 := 

	 := -1

	if  < [] {
		return searchResult{0, , false}
	}

	if  > [] {
		return searchResult{0, len(), false}
	}

	for  <=  {
		 := ( + ) / 2
		 := []

		if  ==  {
			return searchResult{, , true}
		}

		if  <  {

			if  > 0 &&  > [-1] {
				return searchResult{[], , false}
			}

			 = 
		} else {
			if  <  &&  < [+1] {
				return searchResult{[+1],  + 1, false}
			}
			 =  + 1
		}

	}

	return searchResult{[], , false}
}